// @author A0096579E

package rightnow.storage;

import java.util.Deque;
import java.util.LinkedList;

/**
 * StorageStateHolder supports the undo/redo mechanism of the system by storing
 * all previous states of Storage in the form of StorageStates (up to a set limit).
 */
class StorageStateHolder {
	
	private static final int LIMIT = 5;
	
	private Deque<StorageState> undoStates;
	private Deque<StorageState> redoStates;
	
	StorageStateHolder() {
		this.undoStates = new LinkedList<StorageState>();
		this.redoStates = new LinkedList<StorageState>();
	}
	
	/**
	 * Updates the undo history with currentState and clears the redo history.
	 * @param currentState - The last StorageState
	 */
	void updateUndoState(StorageState currentState) {
		// Clear redoStates
		while (!redoStates.isEmpty()) {
			redoStates.pollLast();
		}
		
		addStateTo(undoStates, currentState);
	}
	
	/**
	 * Updates the redo history and returns the next undo state.
	 * @param currentState - The current StorageState
	 * @return The previous StorageState
	 */
	StorageState getUndoState(StorageState currentState) {
		StorageState nextUndoState = undoStates.pollLast();
		if (nextUndoState != null) {
			addStateTo(redoStates, currentState);
		}
		
		return nextUndoState;
	}
	
	/**
	 * Updates the undo history and returns the next redo state
	 * @param currentState - The current StorageState
	 * @return The next StorageState
	 */
	StorageState getRedoState(StorageState currentState) {
		StorageState nextRedoState = redoStates.pollLast();
		if (nextRedoState != null) {
			addStateTo(undoStates, currentState);
		}
		
		return nextRedoState;
	}
	
	private void addStateTo(Deque<StorageState> states, StorageState stateToAdd) {
		if (states.size() >= LIMIT) {
			states.pollFirst();
		}
		states.offerLast(stateToAdd);
	}
	
}
